//
//  TFRequest.h
//  TFFoundation
//
//  Created by TFAppleWork-Summer on 2017/3/20.
//  Copyright © 2017年 TFAppleWork-Summer. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <AFNetworking/AFURLRequestSerialization.h>
#import <AFNetworking/AFURLResponseSerialization.h>
#import <YYModel/YYModel.h>

typedef NSString * kTFRequestAuthorizationHeaderKey NS_STRING_ENUM;
//认证的用户名
__nonnull FOUNDATION_EXPORT kTFRequestAuthorizationHeaderKey const kTFRequestAuthorizationHeaderUsernameKey;
//认证的密码
__nonnull FOUNDATION_EXPORT kTFRequestAuthorizationHeaderKey const kTFRequestAuthorizationHeaderPasswordKey;

/**
 请求方法
 */
typedef NS_ENUM(NSUInteger, TFRequestMethod) {
    /**
     GET请求方法
     */
    TFRequestMethodGet,
    /**
     POST请求方法
     */
    TFRequestMethodPost,
    /**
     HEAD请求方法
     */
    TFRequestMethodHead,
    /**
     PUT请求方法
     */
    TFRequestMethodPut,
    /**
     DELETE请求方法
     */
    TFRequestMethodDelete,
    /**
     PATCH请求方法
     */
    TFRequestMethodPatch,
    /**
     Download请求方法
     */
    TFRequestMethodDownload,
};

/**
 发起请求的解析方式
 */
typedef NS_ENUM(NSUInteger, TFRequestSerializerType) {
    /**
     HTTP请求解析方式
     */
    TFRequestSerializerTypeHTTP,
    /**
     JOSN请求解析方式
     */
    TFRequestSerializerTypeJSON,
    /**
     GZIP请求解析方式
     */
    TFRequestSerializerTypeGZIP,
    /**
     PropertyList请求解析方式
     */
    TFRequestSerializerTypePropertyList,
    /**
     自定义请求解析方式，需设置customRequestSerializer属性，返回对应的requestSerializer
     */
    TFRequestSerializerTypeCustom,
    
};

/**
 返回的解析方式
 */
typedef NS_ENUM(NSUInteger, TFResponseSerializerType) {
    /**
     HTTP返回解析方式
     */
    TFResponseSerializerTypeHTTP,
    /**
     JOSN返回解析方式
     */
    TFResponseSerializerTypeJSON,
    /**
     GZIP返回解析方式
     */
    TFResponseSerializerTypeGZIP,
    /**
     PropertyList返回解析方式
     */
    TFResponseSerializerTypePropertyList,
    /**
     自定义返回解析方式,需设置customResponseSerializer属性，返回对应的responseSerializer
     */
    TFResponseSerializerTypeCustom,
};

/**
 请求状态
 */
typedef NS_ENUM(NSUInteger, TFRequestState) {
    /**
     请求状态--请求未启动
     */
    TFRequestStateNone,
    /**
     请求状态--请求中
     */
    TFRequestStateLoading,
    /**
     请求状态--请求成功
     */
    TFRequestStateSuccess,
    /**
     请求状态--请求错误
     */
    TFRequestStateError,
};

/**
 当前的网络状态
 */
typedef NS_ENUM(NSUInteger, TFRequestCurrentNetStatus) {
    /**
     未知的网络环境
     */
    TFRequestCurrentNetStatusUnknown = -1,
    /**
     未连接的网络环境
     */
    TFRequestCurrentNetStatusNotReachable = 0,
    /**
     3G/4G数据流量网络环境
     */
    TFRequestCurrentNetStatusReachableViaWWAN = 1,
    /**
     wifi网络环境
     */
    TFRequestCurrentNetStatusReachableViaWiFi = 2,
};

@class TFRequest;

/**
 数据请求统一结果处理块

 @param request 请求
 @param response 返回结果
 @param error 返回错误
 */
typedef void(^TFRequestResponseBlock)(__kindof TFRequest * _Nonnull request,_Nullable id response,NSError * _Nullable error);

/**
 数据请求拼接formData处理块

 @param formData 数据
 */
typedef void(^TFConstructingBodyBlock)(_Nonnull id<AFMultipartFormData> formData);

/**
 数据请求统一进度处理块

 @param progress 进度
 */
typedef void(^TFRequestProgressBlock)(float progress);

/**
 检测当前网络环境的处理块

 @param status 当前网络装填
 */
typedef void(^TFRequestCheckNetStatusBlock)(TFRequestCurrentNetStatus status);

/**
 数据请求类
 */
@interface TFRequest : NSObject

/**
 基本的地址
 */
@property (nonatomic, strong, nonnull) NSString *baseURL;

/**
 基本地址后的方法路径地址
 */
@property (nonatomic, strong, nonnull) NSString *path;

/**
 请求参数
 */
@property (nonatomic, strong, nullable) id params;

/**
 请求头部参数
 */
@property (nonatomic, strong, nullable) NSDictionary *requestHeaders;

/**
 请求内容类型
 */
@property (nonatomic, strong, nullable) NSSet *acceptableContentTypesSet;

/**
 请求的认证头部信息
 */
@property (nonatomic, strong, nullable) NSDictionary<kTFRequestAuthorizationHeaderKey,NSString *> *requestAuthorizationHeeader;

/**
 请求方法，默认TFRequestMethodPost
 */
@property (nonatomic, assign) TFRequestMethod requestMethod;

/**
 请求状态
 */
@property (nonatomic, assign, readonly) TFRequestState requestState;

/**
 发送请求的任务类
 */
@property (nonatomic, strong, readonly, nonnull) NSURLSessionTask *sessionTask;

/**
 下载的本地路径
 */
@property (nonatomic, strong, nullable) NSString *downloadLocalPath;

/**
 请求的解析方式，默认TFRequestSerializerTypeHTTP
 */
@property (nonatomic, assign) TFRequestSerializerType requestSerializerType;

/**
 自定义请求Serializer,需指定requestSerializerType为TFRequestSerializerTypeCustom
 */
@property (nonatomic, strong, nullable) __kindof AFHTTPRequestSerializer *customRequestSerializer;

/**
 返回的解析方式，默认TFResponseSerializerTypeJSON
 */
@property (nonatomic, assign) TFResponseSerializerType responseSerializerType;

/**
 自定义请求Serializer,需指定requestSerializerType为TFResponseSerializerTypeCustom
 */
@property (nonatomic, strong, nullable) __kindof AFHTTPResponseSerializer *customResponseSerializer;

/**
 进度block
 */
@property (nonatomic, copy, nullable) TFRequestProgressBlock progressBlock;

/**
 返回结果block
 */
@property (nonatomic, copy, nullable) TFRequestResponseBlock responseBlock;

/**
 拼接body的block
 */
@property (nonatomic, copy, nullable) TFConstructingBodyBlock construtingBodyBlock;

/**
 结果JsonObject映射的class，若设置此属性，会根据josn做自动转换，并返回映射后的对象
 */
@property (nonatomic, strong, nullable) NSString *responseJsonObjectMapClassName;

/**
 映射之后的object
 */
@property (nonatomic, strong, nullable) id responseMapObject;

/**
 返回的数据
 */
@property (nonatomic, strong, readonly, nullable) id responseObject;

/**
 返回的错误
 */
@property (nonatomic, strong, nullable) NSError *error;

/**
 超时时间，默认10.0s
 */
@property (nonatomic, assign) NSTimeInterval timeoutInterval;

/**
 请求花费的时间,单位为s.
 */
@property (nonatomic, assign, readonly) NSTimeInterval costTime;

/**
 是否缓存，默认为NO，若设置为YES，获取responseObject
 */
@property (nonatomic, assign) BOOL isCache;

/**
 缓存的数据
 */
@property (nonatomic, strong, readonly, nullable) id cacheResponseObject;

/**
 返回数据是否是缓存
 */
@property (nonatomic, assign, readonly) BOOL responseObjectIsCache;

/**
 检测当前网络环境,需要手动取消检测

 @param block 变化block
 */
+ (void)checkNetworkStatusUsingBlock:(nullable TFRequestCheckNetStatusBlock)block;

/**
 停止检测网络环境变化
 */
+ (void)stopCheckNetworkStatus;

/**
 将缓存转换成response，通过此方法将responseObject设置为cacheResponseObject，并map.
 */
- (void)convertCacheToResponse;

/**
 清空缓存
 
 @return 是否成功
 */
- (BOOL)clearCache;

/**
 清空所有的TFRequest缓存数据

 @return 是否成功
 */
+ (BOOL)clearAllCache;

/**
 发送请求

 @param responseBlock 返回结果的block
 */
- (void)startRequestWithResponseBlock:(nullable TFRequestResponseBlock)responseBlock;

/**
 发送请求并检测进程

 @param progressBlock 进程block，需要自己回归主线程
 @param responseBlock 返回结果的block
 */
- (void)startRequestWithProgressBlock:(nullable TFRequestProgressBlock)progressBlock responseBlock:(nullable TFRequestResponseBlock)responseBlock;

/**
 发送请求并检测进程和拼接自定义的body

 @param constructingBodyBlock 拼接body的block
 @param progressBlock 进程block，需要自己回归主线程
 @param responseBlock 返回结果的block
 */
- (void)startRequestWithConstructingBodyBlock:(nullable TFConstructingBodyBlock)constructingBodyBlock progressBlock:(nullable TFRequestProgressBlock)progressBlock responseBlock:(nullable TFRequestResponseBlock)responseBlock;

/**
 responseObject当给这个属性赋值的时候会调用此方法，子类可重载此方法定制自己的数据转换

 @param response 返回原始的数据模型
 */
- (void)resetResponseObjectWithResponse:(nullable id)response;

/**
 映射返回的json对象，子类可以通过重载此方法，返回对应的对象，默认JOSNModel转换.
 */
- (void)mapResponseJsonObject;

@end
